#include "StrBufOutStream.h"

#include <string.h>
#include <fan-llvm/core/Core.h>
#include "StrBuf.h"
#include "Type.h"
#include "UnsupportedErr.h"


Type* StrBufOutStream_classType = NULL;
VTable* StrBufOutStream_classVTable = NULL;


/**********************************************
 *
 * Methods and fields
 *
 **********************************************/


/* This write(Int byte) */
OutStream* StrBufOutStream_write(OutStream* self, Int byte)
{
  exceptionThrow(UnsupportedErr_newWithFormattedMsg("Binary write on StrBuf.out"));
  return NULL;
}


/* This writeBuf(Buf buf, Int n) */
OutStream* StrBufOutStream_writeBuf(OutStream* self, Buf* buf, Int n)
{
  exceptionThrow(UnsupportedErr_newWithFormattedMsg("Binary write on StrBuf.out"));
  return NULL;
}


/* This writeChar(Int char) */
OutStream* StrBufOutStream_writeChar(OutStream* self, Int ch)
{
  StrBuf_addChar(((StrBufOutStream*)self)->sb, ch);
  return NULL;
}


/* This writeChars(Str str, Int off, Int len) */
OutStream* StrBufOutStream_writeChars(OutStream* self, Str* str, Int off, Int len)
{
  StrBuf_addSubstr(((StrBufOutStream*)self)->sb, str, off, len - off);
  return NULL;
}


/**********************************************
 *
 * Extra methods
 *
 **********************************************/


/* Create a new StrBufOutStream instance that writes chars to the given StrBuf */
StrBufOutStream* StrBufOutStream_new(StrBuf* sb)
{
  StrBufOutStream* outStream = (StrBufOutStream*)Obj_allocate(sizeof(StrBufOutStream), StrBufOutStream_classVTable);
  OutStream_make((OutStream*)outStream, NULL);
  outStream->sb = sb;
  return outStream;
}


/**********************************************
 *
 * Type-system functions
 *
 **********************************************/


Type* StrBufOutStream_initType(void)
{
  if (StrBufOutStream_classType == NULL)
  {
    Type* baseType = OutStream_initType();
    VTable* vtable = StrBufOutStream_initVTable();
    Type* type = Type_new("StrBufOutStream", baseType, vtable, sizeof(StrBufOutStream), sizeof(StrBufOutStreamVTable));
    Type_registerMethodImplementation(type, "write", StrBufOutStream_write, 1);
    Type_registerMethodImplementation(type, "writeBuf", StrBufOutStream_writeBuf, 2);
    Type_registerMethodImplementation(type, "writeChar", StrBufOutStream_writeChar, 1);
    Type_registerMethodImplementation(type, "writeChars", StrBufOutStream_writeChars, 3);
    StrBufOutStream_classType = type;
    StrBufOutStream_initStatic();
  }
  return StrBufOutStream_classType;
}


VTable* StrBufOutStream_initVTable(void)
{
  if (StrBufOutStream_classVTable == NULL)
  {
    VTable* vtable = memoryAlloc(sizeof(StrBufOutStreamVTable));
    memcpy(vtable, OutStream_initVTable(), sizeof(OutStreamVTable));
    ((OutStreamVTable*)vtable)->write = OutStream_write;
    ((OutStreamVTable*)vtable)->writeBuf = OutStream_writeBuf;
    ((OutStreamVTable*)vtable)->writeChar = OutStream_writeChar;
    ((OutStreamVTable*)vtable)->writeChars = OutStream_writeChars;
    StrBufOutStream_classVTable = vtable;
  }
  return StrBufOutStream_classVTable;
}


void StrBufOutStream_initStatic(void)
{
}
